As Scott Myers wrote, you can take advantage of a relaxation in C++\'s type-system to declare clone() to return a pointer to the actual type being declared:
You could have two methods, a virtual clone() that returns a smart pointer wrapper around the base type, and a non-virtual clone2() that returns the correct type of smart pointer.
clone2 would obviously be implemented in terms of clone and encapsulate the cast.
That way can get the most derived smart pointer that you know at compile time. It may not be the most derived type overall, but it uses all the information available to the compiler.
Another option would be to create a template version of clone that accepts the type you are expecting, but that adds more burden on the caller.