What about creating a static function that returns an allocated pointer to the base class? Within this function you would call new using the correct derived class after determining the file contents.

For example:

class CBase
{
public:
CBase();
static CBase *Create(const CString &strFilename);
};

CBase *CBase::Create(const CString &strFilename)
{
CBase *pRetVal = NULL;

// determine file type
...

// allocate object of correct derived class
pRetVal = new CDerived;

// return allocated pointer to object
return(pRetVal);
}