diff --git a/examples/2_stream_unknown.cpp b/examples/2_stream_unknown.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8ec5340585e0ccb5338720564c4327921d8064ab
--- /dev/null
+++ b/examples/2_stream_unknown.cpp
@@ -0,0 +1,50 @@
+
+#include <iostream>
+#include <sstream>
+#include <cassert>
+#include <cstdlib>
+#include <tscpp.h>
+#include "types.h"
+
+using namespace std;
+using namespace tscpp;
+
+int main()
+{
+    //Declare some types
+    Point2d p2d(1,2);
+    Point3d p3d(3,4,5);
+    MiscData md(p2d,p3d,12,-1);
+    
+    //Prepare a type pool for unserialization
+    TypePool tp;
+    tp.registerType<Point2d>([&](Point2d& t)
+    {
+        cout<<"Found a Point2d"<<endl;
+        assert(t==p2d);
+    });
+    tp.registerType<Point3d>([&](Point3d& t)
+    {
+        cout<<"Found a Point3d"<<endl;
+        assert(t==p3d);
+    });
+    tp.registerType<MiscData>([&](MiscData& t)
+    {
+        cout<<"Found a MiscData"<<endl;
+        assert(t==md);
+    });
+    
+    //Serialize to buffer
+    stringstream ss;
+    OutputArchive oa(ss);
+
+    oa<<p2d<<p3d<<md;
+    
+    //Unserialize from buffer
+    UnknownInputArchive ia(ss,tp);
+    ia.unserialize();
+    ia.unserialize();
+    ia.unserialize();
+    
+    cout<<"Test passed"<<endl;
+}
diff --git a/examples/Makefile b/examples/Makefile
index eb56345f9773054944548f2fbb8d3cdf4d66d02e..5dc24567ba941c1cbe8e04970adfc86001cb3ef7 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -4,11 +4,13 @@ CXXFLAGS = -std=c++11 -O2 -Wall -I..
 
 all:
 	$(CXX) $(CXXFLAGS) 1_stream_known.cpp   ../tscpp.cpp -o 1_stream_known
+	$(CXX) $(CXXFLAGS) 2_stream_unknown.cpp ../tscpp.cpp -o 2_stream_unknown
 	$(CXX) $(CXXFLAGS) 3_buffer_known.cpp   ../tscpp.cpp -o 3_buffer_known
 	$(CXX) $(CXXFLAGS) 4_buffer_unknown.cpp ../tscpp.cpp -o 4_buffer_unknown
 	./1_stream_known
+	./2_stream_unknown
 	./3_buffer_known
 	./4_buffer_unknown
 
 clean:
-	rm -f 1_stream_known 3_buffer_known 4_buffer_unknown
+	rm -f 1_stream_known 2_stream_unknown 3_buffer_known 4_buffer_unknown
diff --git a/tscpp.cpp b/tscpp.cpp
index a058fcb27562127d4ec9c592a460eca207eead3a..b078a8c7437f2362719aa73c70803a7c824ed4de 100644
--- a/tscpp.cpp
+++ b/tscpp.cpp
@@ -46,6 +46,20 @@ int TypePool::unserializeUnknownImpl(const char *name, const void *buffer, int b
     return it->second.size;
 }
 
+void TypePool::unserializeUnknownImpl(const string& name, istream& is, streampos pos) const
+{
+    auto it=types.find(name);
+    if(it==types.end()) {
+        is.seekg(pos);
+        throw TscppException("unknown type",name);
+    }
+
+    unique_ptr<char[]> unserialized(new char[it->second.size]);
+    is.read(reinterpret_cast<char*>(unserialized.get()),it->second.size);
+    if(is.eof()) throw TscppException("eof");
+    it->second.usc(unserialized.get());
+}
+
 int serializeImpl(void *buffer, int bufSize, const char *name, const void *data, int size)
 {
     int nameSize=strlen(name);
@@ -117,32 +131,42 @@ void OutputArchive::serializeImpl(const char *name, const void *data, int size)
 
 void InputArchive::unserializeImpl(const char *name, void *data, int size)
 {
-    pos=is.tellg();
+    auto pos=is.tellg();
     int nameSize=strlen(name);
     unique_ptr<char[]> unserializedName(new char[nameSize+1]);
     is.read(unserializedName.get(),nameSize+1);
-    if(is.eof()) errorImpl("eof");
+    if(is.eof()) throw TscppException("eof");
 
-    if(memcmp(unserializedName.get(),name,nameSize+1))
-        errorImpl("wrong type found",true);
+    if(memcmp(unserializedName.get(),name,nameSize+1)) wrongType(pos);
 
     //NOTE: we are writing on top of a constructed type without calling its
     //destructor. However, since it is trivially copyable, we at least aren't
     //overwriting pointers to allocated memory.
     is.read(reinterpret_cast<char*>(data),size);
-    if(is.eof()) errorImpl("eof");
+    if(is.eof()) throw TscppException("eof");
 }
 
-void InputArchive::errorImpl(const string& errorStr, bool printName)
+void InputArchive::wrongType(streampos pos)
 {
     is.seekg(pos);
-    if(printName==false) throw TscppException(errorStr);
-    else {
-        string type;
-        getline(is,type,'\0');
+    string name;
+    getline(is,name,'\0');
+    is.seekg(pos);
+    throw TscppException("wrong type",name);
+}
+
+void UnknownInputArchive::unserialize()
+{
+    auto pos=is.tellg();
+    string name;
+    getline(is,name,'\0');
+    if(is.eof())
+    {
         is.seekg(pos);
-        throw TscppException(errorStr,type);
+        throw TscppException("eof");
     }
+
+    tp.unserializeUnknownImpl(name,is,pos);
 }
 
 } //namespace tscpp
diff --git a/tscpp.h b/tscpp.h
index f3b9d67139fbc25d9cec03d770e86c6fdf6d55be..9b5070292da56cdeb2038c7c1896ac342666ec81 100644
--- a/tscpp.h
+++ b/tscpp.h
@@ -97,6 +97,11 @@ public:
      */
     int unserializeUnknownImpl(const char *name, const void *buffer, int bufSize) const;
     
+    /**
+     * \internal
+     */
+    void unserializeUnknownImpl(const std::string& name, std::istream& is, std::streampos pos) const;
+    
 private:
     std::map<std::string,UnserializerImpl> types; ///< Registered types
 };
@@ -250,18 +255,17 @@ public:
      * \internal
      */
     void unserializeImpl(const char *name, void *data, int size);
-    
-    /**
-     * \internal
-     */
-    void errorImpl(const std::string& errorStr, bool printName=false);
 
 private:
     InputArchive(const InputArchive&)=delete;
     InputArchive& operator=(const InputArchive&)=delete;
+    
+    /**
+     * \internal
+     */
+    void wrongType(std::streampos pos);
 
     std::istream& is;
-    std::streampos pos;
 };
 
 /**
@@ -281,6 +285,36 @@ InputArchive& operator>>(InputArchive& ia, T& t)
     return ia;
 }
 
+/**
+ * The unknown input archive.
+ * This class allows to unserialize types from a stream which have been
+ * serialized in an unknown order.
+ */
+class UnknownInputArchive
+{
+public:
+    /**
+     * Constructor
+     * \param os ostream where srialized types will be written
+     */
+    UnknownInputArchive(std::istream& is, const TypePool& tp) : is(is), tp(tp) {}
+
+    /**
+     * Unserialize one type from the input stream, calling the corresponding
+     * callback in the TypePool
+     * \throws TscppException if the type found in the stream has not been
+     * registred in the TypePool or if the stream eof is found
+     */
+    void unserialize();
+
+private:
+    UnknownInputArchive(const UnknownInputArchive&)=delete;
+    UnknownInputArchive& operator=(const UnknownInputArchive&)=delete;
+
+    std::istream& is;
+    const TypePool& tp;
+};
+
 /**
  * Exception class thrown by the input archives
  */
@@ -295,8 +329,8 @@ public:
     /**
      * \internal
      */
-    TscppException(const std::string& what, const std::string& t)
-        : runtime_error(what), t(t) {}
+    TscppException(const std::string& what, const std::string& n)
+        : runtime_error(what), n(n) {}
     
     /**
      * If the exception is thrown because an unknown/unexpected type has been
@@ -310,16 +344,16 @@ public:
      * try {
      *     ia>>f;
      * } catch(TscppException& ex) {
-     *     if(ex.type().empty()==false)
-     *         cerr<<"While unserializing Foo, "<<demangle(ex.type())<<" was found\n";
+     *     if(ex.name().empty()==false)
+     *         cerr<<"While unserializing Foo, "<<demangle(ex.name())<<" was found\n";
      * }
      * \endcode
      * \return the serialized type name, or "" if eof was found
      */
-    std::string type() const { return t; }
+    std::string name() const { return n; }
 
 private:
-    std::string t;
+    std::string n;
 };
 
 } // namespace tscpp