Вариант 1: для N объектов создаем массив из N байт, где каждому i соответствует 0/1. 0 - если объект уже использовался, 1 - если еще не использовался. Затем при помощи ГСЧ набираем нужное количество объектов. Минусы: чем меньше объектов, тем дольше мы их будем извлекать.
Вариант 2: заводим связный список. Соответственно, для выбора i-го элемента нам придется пройти i-1 предшествующий. Зато не надо дергаться, когда остается мало элементов, т.к. уже использованные извлекаются из списка. Минусы: необходимость проходить по списку для извлечения объекта.
Вариант 3: связный список + массив. Перед процедурой выбора мы пробегаемся по всему списку и заполняем масссив ссылок. Далее — обычная процедура выбора из массива по индексу с удалением соответствующего элемента из списка. Минусы: каждый раз перед использованием нужно перестраивать массив.
Вариант 4: использовать дерево. Минусы: периодически придется перебалансировать его.
Я рекомендую вариант 3: вроде бы, из предложенных он самый шустрый.
P.S. В жабоскриптике возможен еще вариант: индексы элементов сразу загнать в массив, а как только мы используем какой-то индекс, удалять его из массива. Фактически это вариант 3 с немного меньшим потреблением памяти.