I ended up using chroot to do this, but first I manually changed the UUID of my target disk in grub.cfg on the target disk. I used the blkdev
command to find out the UUID of the target disk partition. It looks something like this ($targetdir is the target filesyste mmounted, $diskdev is the disk device as seen from the host system, e.g. /dev/sdb, and $partitiondev is the disk partition, e.g. /dev/sdb1). At this point I've already partitioned the disk, done mkfs, mounted it, then copied the desired contents of the new filesystem to the disk.
targetuuid=`blkid -s UUID -o value $partitiondev`
test -n "$targetuuid" || error "Could not determine UUID for $partitiondev"
sed --in-place=orig 's/search .*/search --no-floppy --fs-uuid --set=root $targetuuid/' $targetdir/boot/grub/gub.cfg || error "Error setting correct UUID in $targetdir/boot/grub/grub.cfg"
mount -o bind /dev $targetdir/dev
# could also bind other pseudo-filesystems like /proc as in Diblo Dk's answer.
chroot $targetdir grub-install --no-floppy --recheck $diskdev
umount $targetdir/dev # don't forget to unmount this first otherwise you can't unmount $targetdir later
[By the way, in case anyone else encounters a few tangential problems I had in doing this -- I used the "buildroot" tool to make a minimal Linux system in an initramfs to load from a network boot (pxe). If you enable util-linux and select mount/umount under "install utilities", then a slightly broken version of mount is installed (replacing the built-in mount command in busybox), which seems to crash all the time. Also, I had to enable use of devtmpfs in kernel config, and select devtmpfs in buildroot, so that rebinding the /dev filesystem would work -- I guess in the version of busybox I have the bind option to mount only seems to work if you are rebinding a filesystem not a directory within a filesystem.
This is all with buildroot version 2013.05, which uses busybox version 1.21.1, util-linux 2.22.2. Maybe these have been fixed since.]