First of all number of objects doesnt matter much compared to the draw calls you are getting in your game. You have to control the draw calls. Dynamic batching can be applied in this case by using same material for multiple objects(note that there should be no animation and the size of mesh should be small)
if the dynamic batching doesnt work, you can use static batching by marking the object as static, this could be useful for big objects, but needs a Unity PRO license. And you can find the static check box in the inspector at the top right.
Batching: Static batching and Dynamic batching.
if the objects cannot share the same material or texture, you can always do that from code by combining different textures and form a single one and assigning it to a material tht will be shared by different objects. For more assistance on this check this funciton. Also check the below forum links,
Optmize a game in unity
http://answers.unity3d.com/questions/276212/what-is-the-simple-way-of-applying-texture-atlas-t.html, Optmize a game in unity and you can find several other links to get a more clear idea on this.
other than batching you can check for costly shaders that is attached to the objects (especial reflective shaders since number of objects are high).
If you are having textures or a audio files attached to a script using editor, try to avoid them and load it using Resources.Load function. Because the texture or audio file attached to the object will remain in memory until the game object or script instance is deleted.
If you are using OnGUI more, avoid drawing objects that doesnt need update multiple times per frame like label, or a plain texture and enclose in a if loop like the below,
if(Event.current.type == EventType.Repaint)
These are the general optimization techniques i follow. It is hard to tell more since you didnt post any thing related to memory usage, draw calls or a profiler screenshot.
anyway check this link Optmize a game in unity for more info.