Here's what I'm using for view model collections:
Preface:
Your view model objects can be weakly typed. Give IModel a property object Value {get;} and expose that in a ModelViewModel : ViewModel<IModel> that you use for all IModel objects (see my ViewModel<T> implementation below). If you have various combinations of ObservableCollection<IModel>, ICollection<Model<T>>, etc., the framework shown here is a lifesaver. If you still need generic view model, you can derive a ModelViewModel<T> : ModelViewModel that takes a Model<T> in its constructor. The logic to create the appropriate type would go in the converter passed to ViewModelCollection.Create below. Do be warned that this design will impose a performance penalty.
ModelViewModel CreateModelViewModel(IModel model)
{
    Type viewModelType = typeof(ModelViewModel<>).MakeGenericType(model.Type);
    ModelViewModel viewModel = Activator.CreateInstance(viewModelType, model);
    return viewModel;
}
Example usage:
public class CatalogViewModel : ViewModel<ICatalog>
{
    public CatalogViewModel(ICatalog catalog)
        : base(catalog)
    {
        Func<ICatalogProduct, ProductViewModel> viewModelFactory = CreateProductViewModel;
        this.Products = ViewModelCollection.Create(catalog.Products, viewModelFactory);
    }
    public ICollection<ProductViewModel> Products
    {
        get;
        private set;
    }
    private ProductViewModel CreateProductViewModel(ICatalogProduct product)
    {
        return new ProductViewModel(product, this);
    }
}
Benefits:
- Uses lazy implementations to allow for efficient and even recursive bindings in trees.
- The view model collections only implement INotifyCollectionChangedif the underlying model collection implementsINotifyCollectionChanged.
Overview of the classes (full implementations linked to github):
- ViewModel<TModel>: Base class for my view model classes. Exposes a- Modelproperty that I use in the view model's backing code.
 
- ObservableViewModelCollection<TViewModel, TModel>: Lazy (actually not currently, but definitely should be), observable mapping from a model to a view model. Implements- INotifyCollectionChanged.
 
- ViewModelCollection<TViewModel, TModel>: Lazy mapping from a collection of TModel to a collection of- TViewModel.
 
- ViewModelCollection: Static helper - returns an- ICollection<TViewModel>, using- ObservableViewModelCollection<TViewModel, TModel>when the source collection implements- INotifyCollectionChanged, otherwise using- ViewModelCollection<TViewModel, TModel>.
 
A few extra types that might be useful for your view model collections:
ConcatCollection: Like ViewModelCollection, this includes a static helper to automatically choose an appropriate implementation. The ConcatCollection concatenates collections by binding directly to the source collection(s).
Here is an example of how I used this type to expose a Children property to the view while maintaining my observable collections all the way to back to the original source.
public class ProductViewModel : ViewModel<IProduct>
{
    public ProductViewModel(IProduct product)
        : base(product)
    {
        Func<IProduct, ProductViewModel> productViewModelFactory = CreateProductViewModel;
        Func<IRelease, ReleaseViewModel> releaseViewModelFactory = CreateReleaseViewModel;
        this.Products = ViewModelCollection.Create(product.Products, productViewModelFactory);
        this.Releases = ViewModelCollection.Create(product.Releases, releaseViewModelFactory);
        this.Children = ConcatCollection.Create<object>((ICollection)this.Products, (ICollection)this.Releases);
    }
    public IList<ProductViewModel> Products
    {
        get;
        private set;
    }
    public IList<ReleaseViewModel> Releases
    {
        get;
        private set;
    }
    public IEnumerable<object> Children
    {
        get;
        private set;
    }
    private ProductViewModel CreateProductViewModel(IProduct product)
    {
        return new ProductViewModel(product);
    }
    private ReleaseViewModel CreateReleaseViewModel(IRelease release)
    {
        return new ReleaseViewModel(release);
    }
}